package cn.iocoder.yudao.module.worker.service.clerk;

import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.trade.api.config.TradeConfigApi;
import cn.iocoder.yudao.module.trade.api.config.dto.AddressRespDTO;
import cn.iocoder.yudao.module.trade.api.config.dto.TradeConfigRespDTO;
import cn.iocoder.yudao.module.worker.controller.admin.category.vo.CategoryPageReqVO;
import cn.iocoder.yudao.module.worker.controller.admin.category.vo.CategoryRespVO;
import cn.iocoder.yudao.module.worker.controller.admin.goods.vo.WorkerGoodsPageReqVO;
import cn.iocoder.yudao.module.worker.controller.app.category.vo.AppCategoryPageReqVO;
import cn.iocoder.yudao.module.worker.controller.app.clerk.vo.AppClerkPageReqVO;
import cn.iocoder.yudao.module.worker.controller.app.clerk.vo.AppClerkSaveReqVO;
import cn.iocoder.yudao.module.worker.controller.app.goods.vo.AppWorkerGoodsPageReqVO;
import cn.iocoder.yudao.module.worker.dal.dataobject.category.CategoryDO;
import cn.iocoder.yudao.module.worker.dal.dataobject.clerklevel.ClerkLevelDO;
import cn.iocoder.yudao.module.worker.dal.dataobject.goods.WorkerGoodsDO;
import cn.iocoder.yudao.module.worker.dal.mysql.category.CategoryMapper;
import cn.iocoder.yudao.module.worker.dal.mysql.clerklevel.ClerkLevelMapper;
import cn.iocoder.yudao.module.worker.dal.mysql.goods.WorkerGoodsMapper;
import cn.iocoder.yudao.module.worker.dal.mysql.reward.WorkerRewardMapper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.module.worker.controller.admin.clerk.vo.*;
import cn.iocoder.yudao.module.worker.dal.dataobject.clerk.ClerkDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.worker.dal.mysql.clerk.ClerkMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.worker.enums.ErrorCodeConstants.*;

/**
 * 店员信息 Service 实现类
 *
 * @author Jerry
 */
@Service
@Validated
public class ClerkServiceImpl implements ClerkService {

    @Resource
    private ClerkMapper clerkMapper;

    @Resource
    private WorkerGoodsMapper workerGoodsMapper;

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private ClerkLevelMapper clerkLevelMapper;

    @Resource
    private WorkerRewardMapper workerRewardMapper;

    @Resource
    private TradeConfigApi tradeConfigApi;

    @Override
    public Long createClerk(ClerkSaveReqVO createReqVO) {
        // 插入
        ClerkDO clerk = BeanUtils.toBean(createReqVO, ClerkDO.class);
        clerkMapper.insert(clerk);
        // 返回
        return clerk.getId();
    }

    @Override
    public void updateClerk(ClerkSaveReqVO updateReqVO) {
        // 更新
        ClerkDO updateObj = BeanUtils.toBean(updateReqVO, ClerkDO.class);

        ClerkLevelDO clerkLevelDO = clerkLevelMapper.selectById(updateObj.getWorkerClerkLevelId());
        updateObj.setLevel(clerkLevelDO.getLevel());

        clerkMapper.updateById(updateObj);
    }

    @Override
    public void deleteClerk(Long id) {
        // 校验存在
        validateClerkExists(id);
        // 删除
        clerkMapper.deleteById(id);
    }

    private void validateClerkExists(Long id) {
        if (clerkMapper.selectById(id) == null) {
            throw exception(CLERK_NOT_EXISTS);
        }
    }

    @Override
    public ClerkDO getClerk(Long id) {
        return clerkMapper.selectById(id);
    }

    @Override
    public PageResult<ClerkDO> getClerkPage(ClerkPageReqVO pageReqVO) {
        return clerkMapper.selectPage(pageReqVO);
    }

    @Override
    public Long createClerk(AppClerkSaveReqVO createReqVO) {
        // 插入
        ClerkDO clerk = BeanUtils.toBean(createReqVO, ClerkDO.class);
        clerkMapper.insert(clerk);
        // 返回
        return clerk.getId();
    }

    @Override
    public void updateClerk(AppClerkSaveReqVO updateReqVO) {
        // 更新
        ClerkDO updateObj = BeanUtils.toBean(updateReqVO, ClerkDO.class);

        ClerkLevelDO clerkLevelDO = clerkLevelMapper.selectById(updateObj.getWorkerClerkLevelId());
        updateObj.setLevel(clerkLevelDO.getLevel());

        clerkMapper.updateById(updateObj);
    }

    @Override
    public PageResult<ClerkDO> getClerkPage(AppClerkPageReqVO pageReqVO) {
        return clerkMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CategoryRespVO> getGoodsList(Long id) {
        ClerkDO clerkDO = clerkMapper.selectById(id);

        // 取最低店员等级
        ClerkLevelDO clerkLevelDO = clerkLevelMapper.getClerkLevel();

        if(clerkDO.getWorkerClerkLevelId() != null){
            clerkLevelDO = clerkLevelMapper.selectById(clerkDO.getWorkerClerkLevelId());
        }

        List<Long> goodsIdList = JSON.parseObject(clerkDO.getGoodsIdArray(), new TypeReference<List<Long>>(){});
        // 商品缓存
        WorkerGoodsPageReqVO workerGoodsReqVO = new WorkerGoodsPageReqVO();
        workerGoodsReqVO.setGoodsIdList(goodsIdList);
        List<WorkerGoodsDO> goodsList = workerGoodsMapper.selectList(workerGoodsReqVO);
        Map<Long, List<WorkerGoodsDO>> cateMap = new HashMap<>();
        Map<Long, List<WorkerGoodsDO>> cateParentMap = new HashMap<>();
        for(WorkerGoodsDO goods : goodsList){
            goods.setPrice(0);
            if(clerkLevelDO != null){
                if(StringUtils.isNotBlank(clerkLevelDO.getGoodsList())){
                    Map<Long, Integer> goodsMap = JSON.parseObject(clerkLevelDO.getGoodsList(), new TypeReference<Map<Long, Integer>>(){});
                    Integer price = goodsMap.get(goods.getId());
                    if(price != null){
                        goods.setPrice(price);
                    }
                }
            }

            List<WorkerGoodsDO> list = cateMap.get(goods.getCategoryId());
            if(list == null){
                list = new ArrayList<>();
                list.add(goods);
            }else{
                list.add(goods);
            }
            cateMap.put(goods.getCategoryId(), list);

            List<WorkerGoodsDO> parentList = cateParentMap.get(goods.getCategoryParentId());
            if(parentList == null){
                parentList = new ArrayList<>();
                parentList.add(goods);
            }else{
                parentList.add(goods);
            }
            cateParentMap.put(goods.getCategoryParentId(), parentList);
        }

        List<CategoryRespVO> dataList = new ArrayList<>();

        // 分类缓存
        Map<Long, List<CategoryDO>> categoryMap = new HashMap<>();
        CategoryPageReqVO categoryReqVO = new CategoryPageReqVO();
        List<CategoryDO> cateDOList = categoryMapper.selectList(categoryReqVO);
        for(CategoryDO cateDO : cateDOList){
            List<CategoryDO> list = categoryMap.get(cateDO.getParentId());
            if(list == null){
                list = new ArrayList<>();
                list.add(cateDO);
            }else{
                list.add(cateDO);
            }
            categoryMap.put(cateDO.getParentId(), list);
        }

        List<CategoryDO> cateList = categoryMap.get(-1L);
        if(!CollectionUtils.isAnyEmpty(cateList)){
            for(CategoryDO cate : cateList){
                List<WorkerGoodsDO> list = cateMap.get(cate.getId());
                List<WorkerGoodsDO> parentList = cateParentMap.get(cate.getId());
                if(!CollectionUtils.isAnyEmpty(list) || !CollectionUtils.isAnyEmpty(parentList)){
                    CategoryRespVO category = new CategoryRespVO();
                    category.setId(cate.getId());
                    category.setName(cate.getName());
                    // 一级分类
                    if(!CollectionUtils.isAnyEmpty(list)){
                        category.setGoodsList(list);
                    }
                    // 二级分类
                    if(!CollectionUtils.isAnyEmpty(parentList)){
                        category.setRowspan(parentList.size());
                        List<CategoryDO> categoryDOList = categoryMap.get(cate.getId());
                        List<CategoryRespVO> categoryList = new ArrayList<>();
                        for(CategoryDO cateDO : categoryDOList){
                            if(!CollectionUtils.isAnyEmpty(cateMap.get(cateDO.getId()))){
                                CategoryRespVO cateVO = new CategoryRespVO();
                                cateVO.setId(cateDO.getId());
                                cateVO.setName(cateDO.getName());
                                cateVO.setGoodsList(cateMap.get(cateDO.getId()));
                                categoryList.add(cateVO);
                            }
                        }
                        category.setCategoryList(categoryList);
                    }
                    dataList.add(category);
                }
            }
        }
        return dataList;
    }

    @Override
    public WorkerGoodsDO getGoodsById(Long clerkId, Long goodsId) {
        ClerkDO clerkDO = clerkMapper.selectById(clerkId);
        WorkerGoodsDO workerGoodsDO = workerGoodsMapper.selectById(goodsId);

        // 取最低店员等级
        ClerkLevelDO clerkLevelDO = clerkLevelMapper.getClerkLevel();

        if(clerkDO.getWorkerClerkLevelId() != null){
            clerkLevelDO = clerkLevelMapper.selectById(clerkDO.getWorkerClerkLevelId());
        }

        workerGoodsDO.setPrice(0);
        if(clerkLevelDO != null){
            if(StringUtils.isNotBlank(clerkLevelDO.getGoodsList())){
                Map<Long, Integer> goodsMap = JSON.parseObject(clerkLevelDO.getGoodsList(), new TypeReference<Map<Long, Integer>>(){});
                Integer price = goodsMap.get(workerGoodsDO.getId());
                if(price != null){
                    workerGoodsDO.setPrice(price);
                }
            }
        }
        return workerGoodsDO;
    }

    @Override
    public List<ClerkDO> getClerkList(Set<Long> ids) {
        if(CollectionUtils.isAnyEmpty(ids)){
            return CollectionUtils.newArrayList(new ArrayList<>());
        }
        return clerkMapper.selectBatchIds(ids);
    }

    @Override
    public List<ClerkDO> getClerkList(Long userId) {
        return clerkMapper.getClerkList(userId);
    }

    @Override
    public void updateClerkOnlineStatus(Long id, Boolean onlineStatus) {
        ClerkDO clerkDO = clerkMapper.selectById(id);
        clerkDO.setOnlineStatus(onlineStatus);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public void updateClerkBlindStatus(Long id, Boolean blindStatus) {
        ClerkDO clerkDO = clerkMapper.selectById(id);
        clerkDO.setBlindStatus(blindStatus);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public void updateClerkHot(Long id, Boolean hot) {
        ClerkDO clerkDO = clerkMapper.selectById(id);
        clerkDO.setHot(hot);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public void updateClerkHome(Long id, Boolean home) {
        ClerkDO clerkDO = clerkMapper.selectById(id);
        clerkDO.setHome(home);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public List<ClerkDO> getClerkHotList() {
        return clerkMapper.getClerkHotList();
    }

    @Override
    public List<ClerkDO> getClerkNewList() {
        return clerkMapper.getClerkNewList();
    }

    @Override
    public void updateClerkStatus(Long id, Boolean status) {
        ClerkDO clerkDO = clerkMapper.selectById(id);
        clerkDO.setStatus(status);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public List<CategoryRespVO> getAppGoodsList(Long id) {
        ClerkDO clerkDO = clerkMapper.selectById(id);

        // 取最低店员等级
        ClerkLevelDO clerkLevelDO = clerkLevelMapper.getAppClerkLevel();

        if(clerkDO.getWorkerClerkLevelId() != null){
            clerkLevelDO = clerkLevelMapper.selectById(clerkDO.getWorkerClerkLevelId());
        }

        List<Long> goodsIdList = JSON.parseObject(clerkDO.getGoodsIdArray(), new TypeReference<List<Long>>(){});
        if(CollectionUtils.isAnyEmpty(goodsIdList)){
            return CollectionUtils.newArrayList(new ArrayList<>());
        }

        // 商品缓存
        AppWorkerGoodsPageReqVO workerGoodsReqVO = new AppWorkerGoodsPageReqVO();
        workerGoodsReqVO.setGoodsIdList(goodsIdList);
        List<WorkerGoodsDO> goodsList = workerGoodsMapper.selectList(workerGoodsReqVO);
        Map<Long, List<WorkerGoodsDO>> cateMap = new HashMap<>();
        Map<Long, List<WorkerGoodsDO>> cateParentMap = new HashMap<>();
        for(WorkerGoodsDO goods : goodsList){
            goods.setPrice(0);
            if(clerkLevelDO != null){
                if(StringUtils.isNotBlank(clerkLevelDO.getGoodsList())){
                    Map<Long, Integer> goodsMap = JSON.parseObject(clerkLevelDO.getGoodsList(), new TypeReference<Map<Long, Integer>>(){});
                    Integer price = goodsMap.get(goods.getId());
                    if(price != null){
                        goods.setPrice(price);
                    }
                }
            }

            List<WorkerGoodsDO> list = cateMap.get(goods.getCategoryId());
            if(list == null){
                list = new ArrayList<>();
                list.add(goods);
            }else{
                list.add(goods);
            }
            cateMap.put(goods.getCategoryId(), list);

            List<WorkerGoodsDO> parentList = cateParentMap.get(goods.getCategoryParentId());
            if(parentList == null){
                parentList = new ArrayList<>();
                parentList.add(goods);
            }else{
                parentList.add(goods);
            }
            cateParentMap.put(goods.getCategoryParentId(), parentList);
        }

        List<CategoryRespVO> dataList = new ArrayList<>();

        // 分类缓存
        Map<Long, List<CategoryDO>> categoryMap = new HashMap<>();
        AppCategoryPageReqVO categoryReqVO = new AppCategoryPageReqVO();

        TradeConfigRespDTO config = tradeConfigApi.getTradeConfig();
        if(!CollectionUtils.isAnyEmpty(config.getOpenCityAreas())){
            AddressRespDTO address = tradeConfigApi.getAddressByIp(getClientIP());
            categoryReqVO.setIsOline(config.getOpenCityAreas().contains(address.getProvince()));
        }

        List<CategoryDO> cateDOList = categoryMapper.selectList(categoryReqVO);
        for(CategoryDO cateDO : cateDOList){
            List<CategoryDO> list = categoryMap.get(cateDO.getParentId());
            if(list == null){
                list = new ArrayList<>();
                list.add(cateDO);
            }else{
                list.add(cateDO);
            }
            categoryMap.put(cateDO.getParentId(), list);
        }

        List<CategoryDO> cateList = categoryMap.get(-1L);
        if(!CollectionUtils.isAnyEmpty(cateList)){
            for(CategoryDO cate : cateList){
                List<WorkerGoodsDO> list = cateMap.get(cate.getId());
                List<WorkerGoodsDO> parentList = cateParentMap.get(cate.getId());
                if(!CollectionUtils.isAnyEmpty(list) || !CollectionUtils.isAnyEmpty(parentList)){
                    CategoryRespVO category = new CategoryRespVO();
                    category.setId(cate.getId());
                    category.setName(cate.getName());
                    // 一级分类
                    if(!CollectionUtils.isAnyEmpty(list)){
                        category.setGoodsList(list);
                    }
                    // 二级分类
                    if(!CollectionUtils.isAnyEmpty(parentList)){
                        category.setRowspan(parentList.size());
                        List<CategoryDO> categoryDOList = categoryMap.get(cate.getId());
                        List<CategoryRespVO> categoryList = new ArrayList<>();
                        for(CategoryDO cateDO : categoryDOList){
                            if(!CollectionUtils.isAnyEmpty(cateMap.get(cateDO.getId()))){
                                CategoryRespVO cateVO = new CategoryRespVO();
                                cateVO.setId(cateDO.getId());
                                cateVO.setName(cateDO.getName());
                                cateVO.setGoodsList(cateMap.get(cateDO.getId()));
                                categoryList.add(cateVO);
                            }
                        }
                        category.setCategoryList(categoryList);
                    }
                    dataList.add(category);
                }
            }
        }
        return dataList;
    }

    @Override
    public List<CategoryRespVO> getAppBlindGoodsList() {
        // 商品缓存
        AppWorkerGoodsPageReqVO workerGoodsReqVO = new AppWorkerGoodsPageReqVO();
        List<WorkerGoodsDO> goodsList = workerGoodsMapper.selectList(workerGoodsReqVO);
        Map<Long, List<WorkerGoodsDO>> cateMap = CollectionUtils.convertMultiMap(goodsList, WorkerGoodsDO::getCategoryId);
        Map<Long, List<WorkerGoodsDO>> cateParentMap = CollectionUtils.convertMultiMap(goodsList, WorkerGoodsDO::getCategoryParentId);

        List<CategoryRespVO> dataList = new ArrayList<>();

        // 盲盒分类缓存
        AppCategoryPageReqVO categoryReqVO = new AppCategoryPageReqVO();
        categoryReqVO.setBlindStatus(true);
        List<CategoryDO> categoryDOList = categoryMapper.selectList(categoryReqVO);
        Map<Long, List<CategoryDO>> categoryMap = CollectionUtils.convertMultiMap(categoryDOList, CategoryDO::getParentId);

        List<CategoryDO> cateList = categoryMap.get(-1L);
        if(!CollectionUtils.isAnyEmpty(cateList)){
            for(CategoryDO cate : cateList){
                List<WorkerGoodsDO> list = cateMap.get(cate.getId());
                List<WorkerGoodsDO> parentList = cateParentMap.get(cate.getId());
                if(!CollectionUtils.isAnyEmpty(list) || !CollectionUtils.isAnyEmpty(parentList)){
                    CategoryRespVO category = new CategoryRespVO();
                    category.setId(cate.getId());
                    category.setName(cate.getName());
                    // 一级分类
                    if(!CollectionUtils.isAnyEmpty(list)){
                        category.setGoodsList(list);
                    }
                    // 二级分类
                    if(!CollectionUtils.isAnyEmpty(parentList)){
                        category.setRowspan(parentList.size());
                        List<CategoryDO> cateDOList = categoryMap.getOrDefault(cate.getId(), new ArrayList<>());
                        List<CategoryRespVO> categoryList = new ArrayList<>();
                        for(CategoryDO cateDO : cateDOList){
                            if(!CollectionUtils.isAnyEmpty(cateMap.get(cateDO.getId()))){
                                CategoryRespVO cateVO = new CategoryRespVO();
                                cateVO.setId(cateDO.getId());
                                cateVO.setName(cateDO.getName());
                                cateVO.setGoodsList(cateMap.get(cateDO.getId()));
                                categoryList.add(cateVO);
                            }
                        }
                        category.setCategoryList(categoryList);
                    }
                    dataList.add(category);
                }
            }
        }
        return dataList;
    }

    @Override
    public List<ClerkDO> getClerkListByUserId(Long userId) {
        return clerkMapper.getClerkListByUserId(userId);
    }

    @Override
    public ClerkDO getClerkByOrder(Long userId, String sex) {
        return clerkMapper.getClerkByOrder(userId, sex);
    }

    @Override
    public void updateClerkLevel(Long clerkId, Integer sum, Integer weekSum) {
        // 计算打赏佣金
        Integer sumPrice = workerRewardMapper.getSumPrice(clerkId);
        Date time = DateUtil.offsetDay(DateUtil.date(), -7);
        Integer weekSumPrice = workerRewardMapper.getWeekSumPrice(clerkId, DateUtil.toLocalDateTime(time));

        ClerkLevelDO clerkLevelDO = clerkLevelMapper.getClerkLevelByPrice(sum+sumPrice);
        ClerkDO clerkDO = clerkMapper.selectById(clerkId);
        if(clerkLevelDO != null){
            clerkDO.setWorkerClerkLevelId(clerkLevelDO.getId());
            clerkDO.setLevel(clerkLevelDO.getLevel());
        }
        clerkDO.setBrokerageWeekNum(weekSum+weekSumPrice);
        clerkMapper.updateById(clerkDO);
    }

    @Override
    public List<ClerkDO> getWeekTopList(String sex) {
        return clerkMapper.getWeekTopList(sex);
    }

    @Override
    public List<ClerkDO> getNewClerkList() {
        return clerkMapper.getNewClerkList();
    }
}